/*
 * Copyright (c) 2015, Nordic Semiconductor
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package no.nordicsemi.android.nrftoolbox.dfu;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.NotificationManager;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import no.nordicsemi.android.dfu.DfuProgressListener;
import no.nordicsemi.android.dfu.DfuProgressListenerAdapter;
import no.nordicsemi.android.dfu.DfuServiceInitiator;
import no.nordicsemi.android.dfu.DfuServiceListenerHelper;
import no.nordicsemi.android.nrftoolbox.R;
import no.nordicsemi.android.nrftoolbox.ToolboxApplication;
import no.nordicsemi.android.nrftoolbox.UpdateResultActivity;
import no.nordicsemi.android.nrftoolbox.dfu.fragment.UploadCancelFragment;
import no.nordicsemi.android.nrftoolbox.dfu.settings.SettingsFragment;
import no.nordicsemi.android.nrftoolbox.scanner.BleDev;
import no.nordicsemi.android.nrftoolbox.scanner.ScannerFragment;

/**
 * DfuActivity is the main DFU activity It implements DFUManagerCallbacks to receive callbacks from
 * DfuManager class It implements DeviceScannerFragment.OnDeviceSelectedListener callback to receive callback when device is selected from scanning dialog The activity supports portrait and
 * landscape orientations
 */
public class BatchDfuActivity extends AppCompatActivity {
    private static final String TAG = "BatchDfuActivity";

//    private static final String PREFS_DEVICE_NAME = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_DEVICE_NAME";
//    private static final String PREFS_FILE_NAME = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_FILE_NAME";
//    private static final String PREFS_FILE_TYPE = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_FILE_TYPE";
//    private static final String PREFS_FILE_SCOPE = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_FILE_SCOPE";
//    private static final String PREFS_FILE_SIZE = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_FILE_SIZE";

    private static final String DATA_DEVICE = "device";
    private static final String DATA_FILE_TYPE = "file_type";
    private static final String DATA_FILE_TYPE_TMP = "file_type_tmp";
    private static final String DATA_FILE_PATH = "file_path";
    private static final String DATA_FILE_STREAM = "file_stream";
    private static final String DATA_INIT_FILE_PATH = "init_file_path";
    private static final String DATA_INIT_FILE_STREAM = "init_file_stream";
    private static final String DATA_STATUS = "status";
    private static final String DATA_SCOPE = "scope";
    private static final String DATA_DFU_COMPLETED = "dfu_completed";
    private static final String DATA_DFU_ERROR = "dfu_error";

    private static final String EXTRA_URI = "uri";

    private static final int ENABLE_BT_REQ = 0;
    private static final int SELECT_FILE_REQ = 1;
    private static final int SELECT_INIT_FILE_REQ = 2;

    private TextView devNameView;
    private TextView devMacView;
    private TextView deviceNameView;
    private TextView textPercentage;
    private TextView textUploading;
    private TextView updateCount;
    private ProgressBar progressBar;

    private Button uploadButton, connectButton;

    private BleDev selectedDevice;
    private String selectedMac;// = "DC:F8:3C:7A:2D:0F";
    private String selectedDevName;// = "DfuTarg";
    private Uri fileStreamUri;
    private boolean statusOk;
    /** Flag set to true in {@link #onRestart()} and to false in {@link #onPause()}. */
    private boolean resumed;
    /** Flag set to true if DFU operation was completed while {@link #resumed} was false. */
    private boolean dfuCompleted;
    /** The error message received from DFU service while {@link #resumed} was false. */
    private String dfuError;

    ArrayList<String> macList;

    private boolean taskFinished = false;
    int cursor = 0;

    Map<String, String> statusMap = new HashMap<String, String>();

    int successCount = 0;
    int upCount = 0;

    Handler handler = new Handler();

    private DfuServiceInitiator starter;

    /**
     * The progress listener receives events from the DFU Service.
     * If is registered in onCreate() and unregistered in onDestroy() so methods here may also be called
     * when the screen is locked or the app went to the background. This is because the UI needs to have the
     * correct information after user comes back to the activity and this information can't be read from the service
     * as it might have been killed already (DFU completed or finished with error).
     */
    private final DfuProgressListener dfuProgressListener = new DfuProgressListenerAdapter() {
        @Override
        public void onDeviceConnecting(@NonNull final String deviceAddress) {
            progressBar.setIndeterminate(true);
            textPercentage.setText(R.string.dfu_status_connecting);
        }

        @Override
        public void onDfuProcessStarting(@NonNull final String deviceAddress) {
            progressBar.setIndeterminate(true);
            textPercentage.setText(R.string.dfu_status_starting);
            uploadButton.setVisibility(View.VISIBLE);
        }

        @Override
        public void onEnablingDfuMode(@NonNull final String deviceAddress) {
            progressBar.setIndeterminate(true);
            textPercentage.setText(R.string.dfu_status_switching_to_dfu);
        }

        @Override
        public void onFirmwareValidating(@NonNull final String deviceAddress) {
            progressBar.setIndeterminate(true);
            textPercentage.setText(R.string.dfu_status_validating);
        }

        @Override
        public void onDeviceDisconnecting(@NonNull final String deviceAddress) {
            progressBar.setIndeterminate(true);
            textPercentage.setText(R.string.dfu_status_disconnecting);
        }

        @Override
        public void onDfuCompleted(@NonNull final String deviceAddress) {
            textPercentage.setText(R.string.dfu_status_completed);
            if (resumed) {
                // let's wait a bit until we cancel the notification. When canceled immediately it will be recreated by service again.
                new Handler().postDelayed(() -> {
                    onTransferCompleted();

                    // if this activity is still open and upload process was completed, cancel the notification
                    final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                    manager.cancel(DfuService.NOTIFICATION_ID);
                }, 200);
            } else {
                // Save that the DFU process has finished
                dfuCompleted = true;
            }
            Log.d(TAG, "DFU DONE");
            statusMap.put(deviceAddress,"DONE");
            upCount++;
            successCount++;
            setCount();
            statusNext();
        }

        @Override
        public void onDfuAborted(@NonNull final String deviceAddress) {
            textPercentage.setText(R.string.dfu_status_aborted);
            // let's wait a bit until we cancel the notification. When canceled immediately it will be recreated by service again.
            new Handler().postDelayed(() -> {
                onUploadCanceled();

                // if this activity is still open and upload process was completed, cancel the notification
                final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                manager.cancel(DfuService.NOTIFICATION_ID);
            }, 200);

            Log.d(TAG, "onDfuAborted");
            statusMap.put(deviceAddress, "ABORTED");
            upCount++;
            setCount();
            statusNext();

        }

        @Override
        public void onProgressChanged(@NonNull final String deviceAddress, final int percent,
                                      final float speed, final float avgSpeed,
                                      final int currentPart, final int partsTotal) {
            progressBar.setIndeterminate(false);
            progressBar.setProgress(percent);
            textPercentage.setText(getString(R.string.dfu_uploading_percentage, percent));
            if (partsTotal > 1)
                textUploading.setText(getString(R.string.dfu_status_uploading_part, currentPart, partsTotal));
            else
                textUploading.setText(R.string.dfu_status_uploading);
        }

        @Override
        public void onError(@NonNull final String deviceAddress, final int error, final int errorType, final String message) {
            if (resumed) {
                showErrorMessage(message);

                // We have to wait a bit before canceling notification. This is called before DfuService creates the last notification.
                new Handler().postDelayed(() -> {
                    // if this activity is still open and upload process was completed, cancel the notification
                    final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                    manager.cancel(DfuService.NOTIFICATION_ID);
                }, 200);
            } else {
                dfuError = message;
            }
            Log.d(TAG, "onerror");
            statusMap.put(deviceAddress,"ERROR");
            upCount++;
            setCount();
            statusNext();

        }
    };

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_batch_dfu);
        isBLESupported();
        if (!isBLEEnabled()) {
            showBLEDialog();
        }

        Bundle bundle = getIntent().getExtras();
        //String mac = bundle.getString("mac_address");
        macList = bundle.getStringArrayList("SELECTED_DEVICES");
        fileStreamUri = bundle.getParcelable("FILEURI");
        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        cursor = preferences.getInt("cursor", 0);
        String map = preferences.getString("UPDATE_RESULT",null);
        if(map != null) {
            statusMap = JSON.parseObject(map, HashMap.class);
        }
        selectedDevice = JSON.parseObject(macList.get(cursor), BleDev.class);
        selectedMac = selectedDevice.getDevMac();
        selectedDevName = selectedDevice.getDevName();

        statusOk = true;
        setGUI();

        if(ToolboxApplication.fileUri != null) {
            Log.d(TAG, "fileUri is not null");
            Log.d(TAG, JSON.toJSONString(ToolboxApplication.fileUri));
            fileStreamUri = ToolboxApplication.fileUri;
        }

        //uploadButton.setEnabled(statusOk || ToolboxApplication.fileUri != null);
        uploadButton.setVisibility(View.INVISIBLE);

        devNameView = findViewById(R.id.dev_name);
        devNameView.setText(selectedDevName);
        devMacView = findViewById(R.id.dev_mac);
        devMacView.setText(selectedMac);
        updateCount = (TextView) findViewById(R.id.update_count);
        // restore saved state
////        fileType = DfuService.TYPE_AUTO; // Default
////        if (savedInstanceState != null) {
////            fileType = savedInstanceState.getInt(DATA_FILE_TYPE);
////            fileTypeTmp = savedInstanceState.getInt(DATA_FILE_TYPE_TMP);
////            filePath = savedInstanceState.getString(DATA_FILE_PATH);
////            fileStreamUri = savedInstanceState.getParcelable(DATA_FILE_STREAM);
////            initFilePath = savedInstanceState.getString(DATA_INIT_FILE_PATH);
////            initFileStreamUri = savedInstanceState.getParcelable(DATA_INIT_FILE_STREAM);
////            selectedDevice = savedInstanceState.getParcelable(DATA_DEVICE);
////            statusOk = statusOk || savedInstanceState.getBoolean(DATA_STATUS);
////            scope = savedInstanceState.containsKey(DATA_SCOPE) ? savedInstanceState.getInt(DATA_SCOPE) : null;
////            uploadButton.setEnabled(selectedDevice != null && statusOk);
////            dfuCompleted = savedInstanceState.getBoolean(DATA_DFU_COMPLETED);
////            dfuError = savedInstanceState.getString(DATA_DFU_ERROR);
//        }

        DfuServiceListenerHelper.registerProgressListener(this, dfuProgressListener);

        textPercentage.setText("preparing for update...");
        textPercentage.setVisibility(View.VISIBLE);

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                startUpdateProc();
                connectButton.setEnabled(true);
            }
        },3000);



//		try {
//			Thread.sleep(5000);
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
//		fileStreamUri = Uri.parse("content://com.android.externalstorage.documents/document/3383-1106%3Abq_ble_app_uart_s132_dfu_6bytesID_20200817_F.zip");
//		Log.d("URL", String.valueOf(fileStreamUri == null));
//		Log.d("URL", fileStreamUri.toString());
//		final Bundle bundle1 = new Bundle();
//		bundle1.putParcelable(EXTRA_URI, fileStreamUri);
//		getLoaderManager().restartLoader(SELECT_FILE_REQ, bundle1, DfuActivity.this);


    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        DfuServiceListenerHelper.unregisterProgressListener(this, dfuProgressListener);
    }

    @Override
    protected void onSaveInstanceState(@NonNull final Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(DATA_DFU_COMPLETED, dfuCompleted);
        outState.putString(DATA_DFU_ERROR, dfuError);
        outState.putStringArrayList("SELECTED_DEVICES",macList);
        outState.putParcelable("FILEURI",fileStreamUri);
        outState.putInt("CURRENT_CURSOR",cursor);
        outState.putString("SELECTED_MAC", selectedMac);
        outState.putString("SELECTED_DEV_NAME", selectedDevName);
        outState.putString("UPDATE_RESULT", JSON.toJSONString(statusMap));
    }

    private void setGUI() {
        final Toolbar toolbar = findViewById(R.id.toolbar_actionbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);


        deviceNameView = findViewById(R.id.device_name);
        deviceNameView.setText(selectedDevName);

        uploadButton = findViewById(R.id.action_upload);
        connectButton = findViewById(R.id.start_upload);
        connectButton.setEnabled(false);
        textPercentage = findViewById(R.id.textviewProgress);
        textUploading = findViewById(R.id.textviewUploading);
        progressBar = findViewById(R.id.progressbar_file);

        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        if (isDfuServiceRunning()) {
            // Restore image file information

            deviceNameView.setText(selectedDevName);
            devMacView.setText(selectedMac);
            devNameView.setText(selectedDevName);
            statusOk = true;
            showProgressBar();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        resumed = true;
        if (dfuCompleted)
            onTransferCompleted();
        if (dfuError != null)
            showErrorMessage(dfuError);
        if (dfuCompleted || dfuError != null) {
            // if this activity is still open and upload process was completed, cancel the notification
            final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            manager.cancel(DfuService.NOTIFICATION_ID);
            dfuCompleted = false;
            dfuError = null;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        resumed = false;
    }

    private void isBLESupported() {
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            showToast(R.string.no_ble);
            finish();
        }
    }

    private boolean isBLEEnabled() {
        final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        return adapter != null && adapter.isEnabled();
    }

    private void showBLEDialog() {
        final Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableIntent, ENABLE_BT_REQ);
    }

    private void showDeviceScanningDialog() {
        final ScannerFragment dialog = ScannerFragment.getInstance(null); // Device that is advertising directly does not have the GENERAL_DISCOVERABLE nor LIMITED_DISCOVERABLE flag set.
        dialog.show(getSupportFragmentManager(), "scan_fragment");
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        getMenuInflater().inflate(R.menu.result, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
            case R.id.update_result:
                if(taskFinished) {
                    final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
                    final SharedPreferences.Editor editor = sharedPreferences.edit();
                    editor.putString("UPDATE_RESULT", JSON.toJSONString(statusMap));
                    final Intent intent = new Intent(this, UpdateResultActivity.class);
                    intent.putExtra("UPDATE_RESULT",JSON.toJSONString(statusMap));
                    startActivity(intent);
                } else {
                    new AlertDialog.Builder(this)
                            .setTitle("升级任务正在进行中！")
                            .setNeutralButton("确认", null)
                            .show();
                }
                break;
        }
        return true;
    }


    /**
     * Callback of UPDATE/CANCEL button on DfuActivity
     */
    public void startUpdateProc() {
        if (isDfuServiceRunning()) {
            showUploadCancelDialog();
            return;
        }

        // Check whether the selected file is a HEX file (we are just checking the extension)
        if (!statusOk) {
            Toast.makeText(this, R.string.dfu_file_status_invalid_message, Toast.LENGTH_LONG).show();
            return;
        }

        // Save current state in order to restore it if user quit the Activity
        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        final SharedPreferences.Editor editor = preferences.edit();
        //editor.putString(PREFS_DEVICE_NAME, selectedDevice.getName());
        editor.putString("CURRENT_MAC",selectedMac);
        editor.putString("CURRENT_DEV_NAME", selectedDevName);
        editor.putInt("CURRENT_CURSOR", cursor);

        editor.apply();

        showProgressBar();

        final boolean keepBond = preferences.getBoolean(SettingsFragment.SETTINGS_KEEP_BOND, false);
        final boolean forceDfu = preferences.getBoolean(SettingsFragment.SETTINGS_ASSUME_DFU_NODE, false);
        final boolean enablePRNs = preferences.getBoolean(SettingsFragment.SETTINGS_PACKET_RECEIPT_NOTIFICATION_ENABLED, Build.VERSION.SDK_INT < Build.VERSION_CODES.M);
        String value = preferences.getString(SettingsFragment.SETTINGS_NUMBER_OF_PACKETS, String.valueOf(DfuServiceInitiator.DEFAULT_PRN_VALUE));
        int numberOfPackets;
        try {
            numberOfPackets = Integer.parseInt(value);
        } catch (final NumberFormatException e) {
            numberOfPackets = DfuServiceInitiator.DEFAULT_PRN_VALUE;
        }

        /*final*/ /*DfuServiceInitiator*/ starter = new DfuServiceInitiator(selectedMac)
                .setDeviceName(selectedDevName)
                .setKeepBond(keepBond)
                .setForceDfu(forceDfu)
                .setPacketsReceiptNotificationsEnabled(enablePRNs)
                .setPacketsReceiptNotificationsValue(numberOfPackets)
                .setPrepareDataObjectDelay(400)
                .setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true);

            starter.setZip(fileStreamUri, null);


        grantUriPermission(getPackageName(),fileStreamUri,Intent.FLAG_GRANT_READ_URI_PERMISSION);
        starter.start(this, DfuService.class);
    }

    private void showUploadCancelDialog() {
        final LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
        final Intent pauseAction = new Intent(DfuService.BROADCAST_ACTION);
        pauseAction.putExtra(DfuService.EXTRA_ACTION, DfuService.ACTION_PAUSE);
        manager.sendBroadcast(pauseAction);

        final UploadCancelFragment fragment = UploadCancelFragment.getInstance();
        fragment.show(getSupportFragmentManager(), TAG);
    }



    private void showProgressBar() {
        progressBar.setVisibility(View.VISIBLE);
        textPercentage.setVisibility(View.VISIBLE);
        textPercentage.setText(null);
        textUploading.setText(R.string.dfu_status_uploading);
        textUploading.setVisibility(View.VISIBLE);
        //connectButton.setEnabled(false);
        uploadButton.setEnabled(true);
        uploadButton.setText("取消当前设备升级");
    }

    private void onTransferCompleted() {
        clearUI(true);
        showToast(R.string.dfu_success);
    }

    public void onUploadCanceled() {
        clearUI(false);
        showToast(R.string.dfu_aborted);
    }



    private void showErrorMessage(final String message) {
        clearUI(false);
        showToast("Upload failed: " + message);
    }

    private void clearUI(final boolean clearDevice) {
        progressBar.setVisibility(View.INVISIBLE);
        textPercentage.setVisibility(View.INVISIBLE);
        textUploading.setVisibility(View.INVISIBLE);
        //connectButton.setEnabled(true);
        uploadButton.setEnabled(false);
        uploadButton.setText(R.string.dfu_action_upload);
        if (clearDevice) {
            selectedDevice = null;
            deviceNameView.setText(R.string.dfu_default_name);
        }
        // Application may have lost the right to these files if Activity was closed during upload (grant uri permission). Clear file related values.
    }

    private void showToast(final int messageResId) {
        Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show();
    }

    private void showToast(final String message) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }

    private boolean isDfuServiceRunning() {
        final ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (DfuService.class.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

    public void statusNext() {
        //cursor++;
        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        final SharedPreferences.Editor editor = preferences.edit();
        int pcurs = preferences.getInt("CURRENT_CURSOR", 0);
        cursor = Math.max(cursor, pcurs);
        if (cursor >= macList.size() - 1) {
            showToast("升级任务完成！！！");
            taskFinished = true;
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    textUploading.setText("已完成升级所有设备！");
                    textUploading.setVisibility(View.VISIBLE);
                }
            }, 500);

        } else {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    textPercentage.setText("preparing for update next device...");
                    textPercentage.setVisibility(View.VISIBLE);
                    deviceNameView.setText(selectedDevName);
                }
            }, 500);
            cursor++;
            selectedDevice = JSON.parseObject(macList.get(cursor), BleDev.class);
            selectedDevName = selectedDevice.getDevName();
            selectedMac = selectedDevice.getDevMac();
            editor.putString("CURRENT_MAC", selectedMac);
            editor.putString("CURRENT_DEV_NAME", selectedDevName);
            editor.putInt("CURRENT_CURSOR", cursor);
            editor.apply();
            devNameView.setText(selectedDevName);
            devMacView.setText(selectedMac);
            deviceNameView.setText(selectedDevName);

            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    startUpdateProc();

                }
            }, 5000);

        }
    }
    public void setCount() {

        int sum = macList.size();
        StringBuilder sb = new StringBuilder();
        if(upCount > 0) {
            sb.append("已升级设备 ").append(upCount).append( "台, ");
        }
        sb.append("升级成功 ").append(successCount).append( " 台, ");
        sb.append("共 ").append(sum).append(" 台设备");
        updateCount.setText(sb.toString());

    }

}
